<template>
  <div class="container">
    <div class="app-container">
      <el-card v-loading="loading">
        <el-row type="flex" style="height: 60px" align="center">
          <el-button type="primary" size="mini" style="height: 30px" @click="showDialog = true">新增角色</el-button>
        </el-row>
        <el-table
          :data="list"
          style="width: 100%"
        >
          <el-table-column
            type="index"
            :index="indexFn"
            label="ID"
            width="180"
          />
          <el-table-column
            label="角色"
            width="180"
          >
            <template #default="{ row }">
              <el-input v-if="row.isEdit" v-model="row.editRow.name" />
              <span v-else>{{ row.name }}</span>
            </template>
          </el-table-column>
          <el-table-column
            label="描述"
          >
            <template #default="{ row }">
              <el-input v-if="row.isEdit" v-model="row.editRow.description" type="textarea" />
              <span v-else>{{ row.description }}</span>
            </template>
          </el-table-column>
          <el-table-column
            label="状态"
            width="180"
          >
            <!-- 2.6.0 之前的写法 -->
            <!-- <template slot-scope="scope"></template> -->
            <!-- 2.6.0 之后的写法 -->
            <!-- <template v-slot="scope"> -->
            <!-- v-slot 的完整写法是 v-slot:default -->
            <!-- <template v-slot:default="scope"> -->
            <!-- v-slot: 等价于 # 号 -->
            <!-- { row } -->
            <template #default="scope">
              <!-- {{ scope.row.state === 1 ? '启用' : '禁用' }} -->
              <!-- {{ handleState(scope.row.state) }} -->
              <el-switch
                v-if="scope.row.isEdit"
                v-model="scope.row.editRow.state"
                :active-value="1"
                :inactive-value="0"
              />
              <span v-else>
                {{ scope.row.state | handleState }}
              </span>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template #default="{row}">
              <div v-if="row.isEdit">
                <el-button size="mini" @click="cancelEdit(row)">取消</el-button>
                <el-button type="primary" size="mini" @click="btnEditOK(row)">确定</el-button>
              </div>
              <div v-else>
                <el-button type="text" @click="assignPer(row.id)">分配</el-button>
                <el-button type="text" @click="editRole(row)">编辑</el-button>
                <el-button type="text" @click="deleteRole(row.id)">删除</el-button>
              </div>
            </template>
          </el-table-column>
        </el-table>
        <!-- 放置分页组件 -->
        <el-row type="flex" align="middle" justify="center" style="height: 60px">
          <!-- page-sizes 配置每页展示的条数/选项，注意点：page-size 对应的值必须是这个数组里面的某一个 -->
          <!-- $emit('size-change', size) -->
          <el-pagination
            :page-sizes="[2, 4, 6, 8, 10]"
            layout="slot, sizes, prev, pager, next, jumper"
            :page-size="query.pagesize"
            :current-page="query.page"
            :total="total"
            @size-change="changeSize($event)"
            @current-change="changeCurrent"
          >
            <template #default>
              一共{{ total }}条
            </template>
          </el-pagination>
        </el-row>
      </el-card>
      <el-dialog width="500px" title="新增角色" :visible.sync="showDialog" @close="btnCancel">
        <el-form
          ref="formRef"
          label-width="120px"
          :rules="rules"
          :model="roleForm"
        >
          <el-form-item label="角色名称" prop="name">
            <el-input v-model="roleForm.name" style="width:300px" size="mini" />
          </el-form-item>
          <el-form-item label="启用" prop="state">
            <!-- 默认是 true or false 表示打开和关闭的 -->
            <!-- 咱们后端需要的是 1 or 0 表示打开和关闭，可以通过 active-value 和 inactive-value 来控制 -->
            <el-switch v-model="roleForm.state" :active-value="1" :inactive-value="0" size="mini" />
          </el-form-item>
          <el-form-item label="角色描述" prop="description">
            <el-input v-model="roleForm.description" type="textarea" :rows="3" style="width:300px" size="mini" />
          </el-form-item>
          <!-- <el-form-item>
            <el-row type="flex" justify="center">
              <el-col :span="12">
                <el-button type="primary" size="mini">确定</el-button>
                <el-button size="mini">取消</el-button>
              </el-col>
            </el-row>
          </el-form-item> -->
        </el-form>
        <template #footer>
          <el-row type="flex" justify="center">
            <el-col :span="12">
              <el-button type="primary" size="mini" @click="btnOK">确定</el-button>
              <el-button size="mini" @click="btnCancel">取消</el-button>
            </el-col>
          </el-row>
        </template>
      </el-dialog>
      <el-dialog :visible.sync="showPermissionDialog">
        <!-- default-checked-keys 可以执行数组，根据数组里面的 key 来选中，key 到底是啥需要通过 node-key 来指定 -->
        <el-tree ref="permTree" :data="permissionData" :props="{ label: 'name' }" node-key="id" show-checkbox default-expand-all check-strictly :default-checked-keys="permIds" />

        <template #footer>
          <el-row type="flex" align="center">
            <el-col>
              <el-button type="primary" @click="handleAssignPerm">确定</el-button>
              <el-button @click="handlePermCancel">取消</el-button>
            </el-col>
          </el-row>
        </template>
      </el-dialog>
    </div>
  </div>
</template>
<script>
import { getRoleList, delRole, addRole, updateRole, getRoleDetail, assignPerm } from '@/api/role'
import { getPermissionList } from '@/api/permission'
// 过滤器类似于方法，一般用于对模板中的数据进行加工处理
// 所以 Vue3 把过滤器删了
export default {
  name: 'Role',
  data: function() {
    return {
      query: {
        page: 1, // 页码
        pagesize: 10 // 每页展示多少条
      },
      total: 0, // 总条数
      list: [], // 所有数据
      loading: false,
      showDialog: false,
      roleForm: {
        name: '',
        description: '',
        state: 0 // 0 关闭
      },
      rules: {
        name: [{
          required: true,
          message: '角色名称不能为空',
          trigger: 'blur'
        }],
        description: [{
          required: true,
          message: '角色描述不能为空',
          trigger: 'blur'
        }]
      },
      showPermissionDialog: false, // 控制权限弹框的显示隐藏
      permissionData: [], // 装权限数据的
      permIds: [], // 当前角色的权限列表
      currentRoleId: null
    }
  },
  created() {
    this.getRoleList()
  },
  methods: {
    async handleAssignPerm() {
      await assignPerm({
        id: this.currentRoleId,
        permIds: this.$refs.permTree.getCheckedKeys()
      })
      this.$message.success('分配权限成功')
      this.handlePermCancel()
    },
    handlePermCancel() {
      this.showPermissionDialog = false
      // 重置当前角色对应的权限列表
      this.permIds = []
    },
    async assignPer(id) {
      this.currentRoleId = id
      // 获取的所有权限列表
      this.permissionData = this.transListToTreeData(await getPermissionList(), 0)

      // 获取当前角色的详情，这儿需要的是当前角色的权限列表
      const { permIds } = await getRoleDetail(id)
      this.permIds = permIds

      this.showPermissionDialog = true
    },
    async btnEditOK(row) {
      if (row.editRow.name.trim() && row.editRow.description.trim()) {
        // 调用后端接口
        await updateRole({
          ...row.editRow,
          id: row.id
        })
        // this.getRoleList()
        /* row.name = row.editRow.name
        row.description = row.editRow.description
        row.state = row.editRow.state
        row.isEdit = false */
        Object.assign(row, {
          ...row.editRow,
          isEdit: false
        })
        this.$message.success('修改成功')
      } else {
        this.$message.error('请填写 name 和 description')
      }
    },
    editRole(row) {
      row.isEdit = true
    },
    async getRoleList() {
      this.loading = true
      // await getRoleList(this.query) => { total, rows }
      const rows = 888
      console.log(rows)
      const { total, rows: list } = await getRoleList(this.query)
      this.total = total
      this.list = list
      this.loading = false

      // 给 list 中的每一项加一个变量，控制每一行的显示状态
      list.forEach(item => {
        this.$set(item, 'isEdit', false)
        this.$set(item, 'editRow', {
          name: item.name,
          description: item.description,
          state: item.state
        })
      })
    },
    handleState(state) {
      return state === 1 ? '启用' : '禁用'
    },
    changeSize(pagesize) {
      // 改变查询条件，重新发请求
      // pagesize 变了，有可能你当前的页面也会变，建议都从第一页开始要数据
      this.query.page = 1
      this.query.pagesize = pagesize
      this.getRoleList()
    },
    changeCurrent(page) {
      this.query.page = page
      this.getRoleList()
    },
    indexFn(index) {
      // 默认
      // return index + 1
      // 1 => 1 ~ 2
      // 2 => 3 ~ 4
      // 3 => 5 ~ 6
      return index + 1 + (this.query.page - 1) * this.query.pagesize
    },
    deleteRole(id) {
      this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
        type: 'warning'
      }).then(() => {
        // !后端删了
        // 这儿返回一个 Promise，其实又会走后续的 then
        return delRole(id)
      }).then(r => {
        // !后端删除完毕
        // 如果当前页面还剩 1 条数据，我应该请求上一页的数据
        if (this.list.length === 1 && this.query.page > 1) {
          this.query.page--
        }
        // 刷新列表
        this.getRoleList()
        this.$message({
          type: 'success',
          message: '删除成功!'
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    async btnOK() {
      try {
        // #1 兜底校验
        await this.$refs.formRef.validate()
        // #2 调用添加的接口
        await addRole(this.roleForm)
        // #3 重新调用获取数据并更新的接口
        this.getRoleList()
        // #4 提示成功
        this.$message.success('添加角色成功')
        // #5 关闭弹框
        this.btnCancel()
      } catch (e) {
        console.log(e)
      }
    },
    btnCancel() {
      // 重置规则和输入的数据
      this.$refs.formRef.resetFields()
      this.showDialog = false
    },
    cancelEdit(row) {
      row.isEdit = false
      row.editRow.name = row.name
      row.editRow.description = row.description
      row.editRow.state = row.state
    }
  }
}
</script>
